package com.iticit.api.send.service;

import com.iticit.config.CopsPropertyConfig;
import com.iticit.constant.WholeConstants;
import com.iticit.exception.BusinessException;
import com.iticit.util.FileHelper;
import com.iticit.util.HttpClientUtils;
import com.iticit.util.HttpResult;
import com.iticit.util.MD5Utils;
import com.iticit.util.SM2SignUtils;
import com.iticit.util.SM4Utils;
import com.iticit.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Resource;
import lombok.Data;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

@Data
@ToString
@Slf4j
public abstract class CopsBaseService {

	@Resource
	CopsPropertyConfig copsPropertyConfig;

    public String send(String requestJsonReport, String serviceName, String baseRequestUrl) throws Exception {
		log.info("=======start=============current service is {}================", serviceName);
		log.info("original request report---->{}", requestJsonReport);
		//构建Http请求头
		Map<String, String> headerMap =buildHttpHeaderMap(requestJsonReport);
		String requestEncryptJson = headerMap.get("requestEncryptJson");
		headerMap.remove("requestEncryptJson");
		// 获取请求url
        if (StringUtils.isEmpty(baseRequestUrl)){
            baseRequestUrl = copsPropertyConfig.getRequestUrl();
        }
		String requestUrl = baseRequestUrl + "/" + copsPropertyConfig.getInvokeService() + "/" + serviceName + "/" + copsPropertyConfig
				.getInterfaceVersion();
		log.info("request url is {}", requestUrl);
		// 发送请求到广发金融开放平台
		HttpResult result = HttpClientUtils.sendHttpPostWithCustomHeader(requestUrl, requestEncryptJson, headerMap);
		// 响应报文原文(为加密串)
		String responseJson = result.getResult();
	    // 验签通过即返回解密后的报文
	    return decryptAndVerySign(result.getHeaderMap().get("signature"),responseJson,serviceName);
	}

	public Map<String, String> buildHttpHeaderMap(String requestJsonReport) throws Exception {
		// 对原报文加密
		String requestEncryptJson = SM4Utils.SM4EncryptData(copsPropertyConfig.getEncryptKey(), requestJsonReport, copsPropertyConfig
				.getEncoding());
		log.info("request report after encrypting---->encryptKey[{}]----->{}", copsPropertyConfig.getEncryptKey(), requestEncryptJson);
		// 对原报文签名
		String requestSignatureJson = SM2SignUtils.signString(requestJsonReport, FileHelper.loadFileBytes(
				copsPropertyConfig.getKeyBasePath(), copsPropertyConfig.getPrivateKey()), copsPropertyConfig.getEncoding());
		// 证书ID，使用公钥MD5值
		String certId = MD5Utils.getMD5(FileHelper.loadFileBytes(
				copsPropertyConfig.getKeyBasePath(), copsPropertyConfig.getPublicKey()));
		log.info("certId----->{}", certId);
		log.info("request report after signing---->{}", requestSignatureJson);
		// 对报文加密密钥加密，使用广发公钥进行加密
		String keyToEncry = SM2SignUtils.encryptString(FileHelper.loadFileBytes(copsPropertyConfig.getKeyBasePath(), copsPropertyConfig
				.getCompanyPublicKey()), copsPropertyConfig.getEncryptKey(), copsPropertyConfig.getEncoding());
		// http请求头创建
		Map<String, String> headerMap = new HashMap<>();
		headerMap.put("requestEncryptJson",requestEncryptJson);
		headerMap.put("certId", certId);
		headerMap.put("signature", requestSignatureJson);
		headerMap.put("signType", "SM2");
		headerMap.put("Content-Type", "application/json;charset=UTF-8");
		headerMap.put("encryptType", "SM4");
		headerMap.put("encryptKey", keyToEncry);
		return headerMap;
	}

	public String  decryptAndVerySign(String responseSignature,String originJson,String serviceName) throws Exception {
		log.info("source response report--->{}", originJson);
		// 响应报文解密
		String responseDecryptJson = SM4Utils.SM4DecryptData(copsPropertyConfig.getEncryptKey(), originJson, copsPropertyConfig
				.getEncoding());
		log.info("response report after decrypting--->{}", responseDecryptJson);
		// 响应报文验签
		boolean veriyfyResult = SM2SignUtils.verifySignString(FileHelper.loadFileBytes(copsPropertyConfig.getKeyBasePath(), copsPropertyConfig
				.getCompanyPublicKey()), responseSignature, responseDecryptJson, copsPropertyConfig.getEncoding());
		log.info("verifying signature of response report is {}", veriyfyResult);
		if(!veriyfyResult) {
			throw new BusinessException(WholeConstants.CopsMsg.VERIFY_SIGN_NOT_PASS);
		}
		log.info("=======end===============current service is {}================", serviceName);
		// 验签通过即返回解密后的报文
		return responseDecryptJson;
	}
}
